package top.zlhy7.lock;

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * @author renyong
 * @date 2022/8/2 21:27
 * @description 公平锁与非公平锁
 */
/*
    非公平锁
        缺点：可能导致线程饿死，synchronized关键字就属于非公平锁
        优点：效率高，插队
    公平锁
        缺点：效率相比非公平锁低一点
        优点：阳光普照，即都有获得锁的机会，排队
    可重入锁 synchronized，lock都属于


 */
public class TheadDemo5 {
    /**
     * 票数
     */
    private int number = 30;
    /**
     * 创建一个公平锁
     */
    private Lock lock = new ReentrantLock(true);

    /**
     * 卖票
     */
    public void sale(){
        lock.lock();
        try {
            if(number<1){
                return;
            }
            System.out.println(Thread.currentThread().getName()+"：卖出"+(number--)+"剩余："+number);
        }finally {
            lock.unlock();
        }
    }

    public int getNumber() {
        return number;
    }

    /**
     * 测试公平锁
     */
    public static void test1(){
        TheadDemo5 theadDemo5 = new TheadDemo5();
        new Thread(()->{
            for (int i = 0; i < 30; i++) {
                theadDemo5.sale();
            }
        },"售票员1").start();
        new Thread(()->{
            for (int i = 0; i < 30; i++) {
                theadDemo5.sale();
            }
        },"售票员2").start();
        new Thread(()->{
            for (int i = 0; i < 30; i++) {
                theadDemo5.sale();
            }
        },"售票员3").start();
    }
    public synchronized void add(){
        add();
    }
    /**
     * 测试可重入锁
     */
    public static void test2(){
        Object obj = new Object();
        new Thread(()->{
            synchronized (obj){
                System.out.println(Thread.currentThread().getName()+"外层");
                synchronized (obj){
                    System.out.println(Thread.currentThread().getName()+"中层");
                    synchronized (obj){
                        System.out.println(Thread.currentThread().getName()+"内层");
                    }
                }
            }
            System.out.println();
        },"t1").start();
    }
    public static void main(String[] args) {
        test2();
    }
}
